/*
 * mytcp.h
 *
 *  Created on: 2009-3-30
 *      Author: tian
 */

#ifndef MYTCP_H_
#define MYTCP_H_

#include"mytcpstate.h"
#include"ipaddr.h"
#include"myip.h"
#include"mysocket.h"
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
//
#ifndef BUFLEN
#define BUFLEN 100
#endif

//bits
#define DEFAULT_TCP_HEADER_LENGTH 160

struct tcphdr{
	//should be 16-bit source port
	unsigned short tcp_sport;
	//should be 16-bit destination port
	unsigned short tcp_dport;
	//should be 32-bit sequence number
	unsigned long tcp_seq;
	//should be 32-bit acknowledge number
	unsigned long tcp_ack;
	struct hl_flag{
		//should be 4-bit length of tcp header
		unsigned char hl:4;
		unsigned char :4;
		unsigned char :2;
		unsigned char urg:1;
		unsigned char ack:1;
		unsigned char psh:1;
		unsigned char rst:1;
		unsigned char syn:1;
		unsigned char fin:1;
		//should be 16-bit window size
		unsigned short tcp_win:16;
	}tcp_hl_flag;
	//should be 16-bit checksum
	unsigned short tcp_sum;
	//should be 16-bit urgent pointer
	//but in our design, it should always 0
	unsigned short tcp_up;
};

/*ip fake header?,for tcp check_sum
 * ...
 */
struct ip_fake_hdr{
	struct in_addr des;	/*destination ip address*/
	struct in_addr src;	/*source ip address*/
	unsigned char mbz;	/*null*/
	unsigned char pro;	/*protocal*/
	unsigned short tcp_l;	/*length of tcp package*/
};

//this struct should be discussed
//some element is not needed
//some element shouble be added
struct tcpcb{
	pid_t pid;			/*pid of associated process*/
	int sock;			/*socket of associated*/
	int tcp_state;	/*the state of tcp*/
	unsigned long seq;/*current available seq*/
	unsigned long peerseq;/*peer seq*/
	int timer[4];			/*tcp timer*/
	struct sockaddr sock_addr;
	int q2num;			/*listen completed queue number*/
	int q2beg;			/*listen completed queue begin*/
	int q2end;			/*listen completed queue end*/
	struct sockaddr *queue2;/*listen queue pointer*/
	int msgqid;			/*process related message queue*/
	int pipeid;			/*process related fifo pipe*/
	struct tcpcb *next;	/*next tcpcb*/
	char sndbuf[BUFLEN];/*send buffer*/
	int sndlen;
	char recbuf[BUFLEN*2];/*recieve buffer*/
	int recbeg;
	int recend;

	struct tcphdr lasthdr;
};

/*a header of tcpcb list*/
struct tcpcb *head;

enum{
	event_null=0,
	active_open,
	passive_open,
	send_data,
	close_sock,
	timeout,
};

/* this function send tcp data to ip layer.it will change
 * tcp_state in tcpcb if some condition is satisfied.
 * Parameter:
 * ptcpheader:a pointer to the tcp header which the packge contains
 * buf:a buffer which contains data
 * buflen:the length of buffer
 * ptcpcb:a pointer pointed to the associated tcpcb
 * Return Values:
 * it returns -1 for some error,and 0 is returned if succeed
*/
int tcp_output(struct tcphdr *ptcpheader,char *buf,unsigned int buflen,struct tcpcb* ptcpcb);

/* this function handles tcp data which is received from ip
 * layer, it should check these data, make sure check_sum as
 * well as and sequence is right and send data to user level.
 * it will change tcp_state in tcpcb if some condition is
 * satisfied.
 * Parameter:
 * p_ip_fhdr:a pointer pointed to the associated ip fake header
 * tcppkg:a pointer pointed to tcp package
 * ptr:a pointer pointed to the tcpcb
 * event:some event
 * Return values:
 * it returns -1 for some error,and 0 is returned if succeed
 */
int tcp_input(struct ip_fake_hdr* p_ip_fhdr,void* tcppkg,struct tcpcb* ptr,int event);

/* this function watches all the network timers which is in
 * every tcpcb nodes.when a time out is happen, it will handle
 * the work to tell user(socket).It wakes up in every servral
 * secones,and then reduce tcpcb timers in every tcpcb.
 * when a timer reduces to 0, it means some work is time out.
 */
int tcp_timer();

/* this function check a tcp check sum whether is correct.
 * it will change tcp_state in tcpcb if some condition is
 * satisfied.
 * Parameter:
 * Return Values:
 * it returns -1 if the check sum is wrong, and 0 is returned
 * if correct.
 */
unsigned short tcp_checksum(struct ip_fake_hdr *p_ip_fhdr,void *tcppkg);

/* this function create a new tcpcb nodes.
 * Parameter:
 * some elements in struct tcpcb is not decided, this part should
 * be determined when struct tcpcb is certain.
 * Return Values:
 * it will return a NULL pointer if creation is failed, and a
 * pointer to the new tcpcb is returned if succeed.
 */
struct tcpcb* tcp_new_tcpcb();

/* this function finds the tcpcb associated with the special
 * ip address and port.
 * Parameter:
 * psockaddr:a pointer pointed to a sockaddr
 * Return Values:
 * it will return a NULL pointer if tcpcb does not exist,and the
 * pointer will be returned if found.
 */
struct tcpcb* get_tcpcb(struct sockaddr *psockaddr);
struct tcpcb* get_tcpcb_by_sock(pid_t pid,int sock);

#endif /* MYTCP_H_ */
